/*
 *  Copyright 2019-2023 oyun
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.oyun.modules.province.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oyun.modules.province.domain.Area;
import com.oyun.modules.province.domain.vo.AreaQueryCriteria;
import com.oyun.modules.province.mapper.AreaMapper;
import com.oyun.modules.province.service.AreaService;
import com.oyun.utils.FileUtil;
import com.oyun.utils.PageResult;
import com.oyun.utils.PageUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author aoyun
 * @description 服务实现
 * @date 2024-04-25
 **/
@Service
@RequiredArgsConstructor
public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements AreaService {

    private final AreaMapper areaMapper;

    @Override
    public PageResult<Area> queryAll(AreaQueryCriteria criteria, Page<Object> page) {
        return PageUtil.toPage(areaMapper.findAll(criteria, page));
    }

    @Override
    public List<Area> queryAll(AreaQueryCriteria criteria) {
        return areaMapper.findAll(criteria);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(Area resources) {
        save(resources);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Area resources) {
        Area area = getById(resources.getId());
        area.copy(resources);
        saveOrUpdate(area);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(List<Long> ids) {
        removeBatchByIds(ids);
    }

    @Override
    public void download(List<Area> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (Area area : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("编码", area.getCode());
            map.put("地区名称", area.getAreaName());
            map.put("地区蒙文", area.getAreaNameM());
            map.put("父编码", area.getParentCode());
            map.put("等级", area.getLevel());
            map.put("经度", area.getLng());
            map.put("纬度", area.getLat());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public List<Area> getAreaTreeList() {
        //所有的分类
        List<Area> categoryList = areaMapper.selectList(null);
        //所有分类id集合
        List<String> idList = categoryList.stream().map(Area::getCode).collect(Collectors.toList());
        //返回的树分类结果
        List<Area> treeCategory = new ArrayList<>();
        //一级分类目录
        List<Area> categories = categoryList.stream().filter(category -> !idList.contains(category.getParentCode())).collect(Collectors.toList());
        //循环当前一级分类目录
        for (Area category : categories) {
            //给当前分类节点 添加 子分类节点
            addChild(categoryList, category);
            //当前分类添加完子节点分类之后，添加到返回的树结构中
            treeCategory.add(category);
        }
        //把返回的树结构返回
        return categories;

    }

    public void addChild(List<Area> categoryList, Area category) {
        //循环所有的分类，获取当前节点的所有子节点
        List<Area> categoryListChild = categoryList.stream().filter(category1 -> category1.getParentCode().equals(category.getCode())).collect(Collectors.toList());
        //把当前分类的子节点添加到当前分类
        category.setChildrenList(categoryListChild);
        //再次调用本方法,把当前节点的子节点当成当前节点，继续添加子节点,备注：这样会造成一直循环
        categoryListChild.forEach(category1 -> {
            //添加一步，判断当前节点是否有子节点，没有就不循环递归
            if (haveChild(categoryList, category1)) {
                addChild(categoryList, category1);
            }
        });
    }

    public boolean haveChild(List<Area> categoryList, Area category) {
        //获取当前节点的子节点
        List<Area> categoryListChild = categoryList.stream().filter(category1 -> category1.getParentCode().equals(category.getCode())).collect(Collectors.toList());
        //子节点大于0则存在，否则不存在
        return categoryListChild != null && categoryListChild.size() > 0;
    }
}

